

import { OrderSide, OrderStatus, PositionSide, numberInString } from "binance";
import EventEmitter from "events";
import { throttle } from "lodash";
import { AutoTradeType } from "./types";

export interface Order{
  clientOrderId?: numberInString;
  orderId?: numberInString;
  price: numberInString;
  side: OrderSide;
  positionSide?: PositionSide;
  status: OrderStatus;
  symbol: string;
  tradeType: AutoTradeType;
}
interface EventMap {
  'maybeFilled':  (order: Order) => void
}

export class OrderWatch<T extends Order = Order> {
  private orders: Record<string, T[]> = {};
  private eventEmitter: EventEmitter;

  constructor() {
    this.eventEmitter = new EventEmitter();
  }
  getKey(order: {symbol: string; tradeType: AutoTradeType}) {
    return `${order.symbol}-${order.tradeType}`;
  }
  // 添加订单
  addOrder(order: T) {
    const key = this.getKey(order);
    if (!this.orders[key]) {
      this.orders[key] = [];
    }
    if (order.price && order.price != 0) {
      if (order.status === 'NEW' || order.status === 'PARTIALLY_FILLED') {
        this.orders[key].push(order);
      }
    }
  }
  clear(symbol: string, tradeType: AutoTradeType) {
    const key = this.getKey({symbol, tradeType});
    this.orders[key] = [];
  }
  removeOrder(order: Pick<T, 'clientOrderId' | 'tradeType' | 'symbol'>) {
    const key = this.getKey(order);
    if (!this.orders[key]) {
      return;
    }
    for (let i = 0; i < this.orders[key].length; i++) {
      if (order.clientOrderId === order.clientOrderId) {
        this.orders[key].splice(i, 1);
        i--;
      }
    }
  }

  // 更新市场价格
  updatePrice(symbol: string, tradeType: AutoTradeType, currentPrice: number) {
    this.checkOrderStatus(symbol, tradeType, currentPrice);
  }

  // 检查是否订单价格触发
  checkOrderStatus(symbol: string, tradeType: AutoTradeType, currentPrice: number) {
    if (currentPrice <= 0) {
      return;
    }
    const orders = this.orders[this.getKey({symbol, tradeType})] || []
    for (let i = 0; i < orders.length; i++) {
      const order = orders[i];

      if (order.price === 0 || order.tradeType !== tradeType) {
        // outLogger.info(`order.price`, order)
        continue
      }
      if (order.side === 'BUY') {
        if (currentPrice <= Number(order.price)) {
          this.emitOrderTriggeredEvent(order);
          orders.splice(i, 1);
          i--;
        }
      } else if (order.side === 'SELL') {
        if (currentPrice >= Number(order.price)) {
          this.emitOrderTriggeredEvent(order);
          orders.splice(i, 1);
          i--;
        }
      }
    }
  }
  // 发出订单触发事件
  private emitOrderTriggeredEvent = throttle((order: Order) => {
    this.emit('maybeFilled', order);
  }, 1000 * 10, { leading: true})

  on<E extends keyof EventMap>(event: E, callback: EventMap[E]) {
    this.eventEmitter.on(event, callback);
  }
  emit<E extends keyof EventMap>(event: E, ...params: Parameters<EventMap[E]>) {
    this.eventEmitter.emit(event, ...params);
  }

  distory() {
    this.eventEmitter.removeAllListeners();
    this.orders = null;
  }
}